#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
import os
import threading
import logging
import re
import asyncio
from datetime import datetime
from bs4 import BeautifulSoup

import db
import download_m3u8
import hlsutils
import blogutils

import settings
from logger import set_logger


def goto_dir(path):
    data = []
    try:
        session = db.create_session()
        data = [item.dobule_to_dict() for item in session.query(
            db.Fileitem).filter_by(path=path).order_by(db.Fileitem.updated_at.desc())]
        for item in data:
            if item['content_type'] == 'hls':
                hlsitem = session.query(db.Hlsitem).filter_by(
                    id=item.get('item_id', None)).first()
                if hlsitem:
                    item['uri'] = hlsitem.url
                    item['duration'] = hlsitem.duration
                    item['size'] = hlsitem.size
                    item['status'] = hlsitem.status
                    item['updated_at'] = hlsitem.updated_at
            if item['content_type'] == 'blog':
                blogitem = session.query(db.Blog).filter_by(
                    id=item.get('item_id', None)).first()
                if blogitem:
                    item['summary'] = blogitem.summary
                    item['content'] = blogitem.content
                    item['status'] = blogitem.status
                    item['updated_at'] = blogitem.updated_at
        data.sort(key=lambda el: el['content_type'] != 'd')
    except BaseException as e:
        logging.error('[ERROR] goto_dir: %s' % e)
        data = []
    return {'files': data, 'path': path[1:].split('/')}


def makedir(parent, name):
    try:
        session = db.create_session()
        pparent, parent_name = parent.rsplit('/', 1)
        if len(pparent) <= 0:
            pparent = None
        if len([item for item in session.query(db.Fileitem).filter_by(name=parent_name, path=pparent, content_type='d')]) <= 0:
            return {'status': False, 'msg': '父文件夹(%s)不存在' % parent}
        if len([item for item in session.query(db.Fileitem).filter_by(name=name, path=parent)]) > 0:
            return {'status': False, 'msg': '文件[%s/%s]重名' % (parent, name)}
        fileitem = db.Fileitem(name=name, path=parent, content_type='d')
        session.add(fileitem)
        session.commit()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def mkdirs(fullpath):
    print('-' * 65)
    print(fullpath)
    print('-' * 65)
    session = db.create_session()
    ppath, pname = fullpath.rsplit('/', 1)
    if len(ppath) > 0:
        fileitem = session.query(db.Fileitem).filter_by(
            name=pname, path=ppath).first()
        if fileitem:
            return
        mkdirs(ppath)
        fileitem = db.Fileitem(name=pname,
                               path=ppath, content_type='d')
        session.add(fileitem)
        session.commit()
    else:
        parent, name = (None, pname)
        fileitem = session.query(db.Fileitem).filter_by(
            name=name, path=parent).first()
        if fileitem:
            return


def import_data(data):
    try:
        session = db.create_session()
        paths = []
        fileitem_exists = []
        fileitem_not_exists_blog = []
        fileitem_not_exists_hls = []
        logging.warning('data: %s' % data)
        for item in data:
            if 'content_type' in item:
                if not 'name' in item or not 'path' in item:
                    logging.error('[--]文件[%s/%s]格式不正确: %s' %
                                  (item['path'], item['name'], item))
                    return {'status': False, 'msg': '文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
            else:
                logging.error('[---]文件[%s/%s]格式不正确: %s' %
                              (item['path'], item['name'], item))
                return {'status': False, 'msg': '文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
            fileitem = session.query(db.Fileitem).filter_by(
                name=item['name'], path=item['path']).first()
            if fileitem:
                logging.warning('[-]文件[%s/%s]已存在' %
                                (item['path'], item['name']))
                fileitem_exists.append(item)
            else:
                if item['content_type'] == 'd' and '%s/%s' % (item['path'], item['name']) not in paths:
                    paths.append('%s/%s' % (item['path'], item['name']))
                if item['content_type'] == 'hls':
                    fileitem_not_exists_hls.append(item)
                if item['content_type'] == 'blog':
                    fileitem_not_exists_blog.append(item)
                if item['path'] not in paths:
                    paths.append(item['path'])
        logging.warning('paths: %s' % paths)
        logging.warning('fileitem_exists: %s' % fileitem_exists)
        logging.warning('fileitem_not_exists_hls: %s' %
                        fileitem_not_exists_hls)
        logging.warning('fileitem_not_exists_blog: %s' %
                        fileitem_not_exists_blog)
        for path in paths:
            mkdirs(path)
        if len(fileitem_not_exists_hls) > 0:
            import_hls = hlsutils.import_data(fileitem_not_exists_hls)
            if import_hls['status']:
                for item in import_hls['msg']:
                    fileitem = db.Fileitem(
                        item_id=item.id, name=item.name, path=item.path, poster=item.poster, content_type='hls')
                    session.add(fileitem)
                session.commit()
            else:
                logging.error('[Error]: import hls %s' % import_hls['msg'])
        if len(fileitem_not_exists_blog) > 0:
            import_blog = blogutils.import_data(fileitem_not_exists_blog)
            if import_blog['status']:
                for item in import_blog['msg']:
                    fileitem = db.Fileitem(
                        item_id=item.id, name=item.name, path=item.path, content_type='blog')
                    session.add(fileitem)
                session.commit()
            else:
                logging.error('[Error]: import blog %s' % import_blog['msg'])
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': len(data)}


def export(parent, name):
    try:
        session = db.create_session()
        fileitem = session.query(db.Fileitem).filter_by(
            name=name, path=parent).first()
        if not fileitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        result = []
        if fileitem.content_type == 'd':
            fullpath = '%s/%s' % (parent, name)
            if not parent:
                fullpath = name
            result.append({'path': fileitem.path, 'name': fileitem.name,
                           'content_type': fileitem.content_type, 'referer': fileitem.referer})
            child_files = session.query(db.Fileitem).filter(
                db.Fileitem.path.like('%s%%' % fullpath))
            for item in child_files:
                result.append({'path': item.path, 'name': item.name, 'content_type': item.content_type, 'referer': item.referer,
                               'referer_referer': item.referer_referer, 'poster': item.poster, 'poster_referer': item.poster_referer})
        else:
            result.append({'path': fileitem.path, 'name': fileitem.name, 'content_type': fileitem.content_type, 'referer': fileitem.referer,
                           'referer_referer': fileitem.referer_referer, 'poster': fileitem.poster, 'poster_referer': fileitem.poster_referer})
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def file_export(fullpath):
    try:
        parent, name = fullpath.rsplit('/', 1)
        if len(parent) <= 0:
            parent = None
        session = db.create_session()
        fileitem = session.query(db.Fileitem).filter_by(
            name=name, path=parent).first()
        if not fileitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        result = []
        if fileitem.content_type == 'd':
            result.append({'path': fileitem.path, 'name': fileitem.name,
                           'content_type': fileitem.content_type})
            child_files = session.query(db.Fileitem).filter(
                db.Fileitem.path.like('%s%%' % fullpath))
            for item in child_files:
                if item.content_type == 'hls':
                    export_result = hlsutils.hls_export(
                        '%s/%s' % (item.path, item.name))
                    if export_result['status']:
                        for hlsitem in export_result['msg']:
                            result.append(hlsitem)
                if item.content_type == 'blog':
                    export_result = blogutils.blog_export(
                        '%s/%s' % (item.path, item.name))
                    if export_result['status']:
                        for blogitem in export_result['msg']:
                            result.append(blogitem)
        else:
            if fileitem.content_type == 'hls':
                export_result = hlsutils.hls_export(
                    '%s/%s' % (fileitem.path, fileitem.name))
                if export_result['status']:
                    for hlsitem in export_result['msg']:
                        result.append(hlsitem)
            if fileitem.content_type == 'blog':
                export_result = blogutils.blog_export(
                    '%s/%s' % (fileitem.path, fileitem.name))
                if export_result['status']:
                    for blogitem in export_result['msg']:
                        result.append(blogitem)
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def save_blog(blog):
    try:
        session = db.create_session()
        mkdirs(blog.path)
        fileitem = session.query(db.Fileitem).filter_by(
            item_id=blog.id, content_type='blog').first()
        if fileitem:
            fileitem.name = blog.name
            fileitem.updated_at = datetime.now()
            fileitem.updated_date = fileitem.updated_at.strftime('%Y%m%d')
            fileitem.updated_stamp = fileitem.updated_at.timestamp()
        else:
            fileitem = db.Fileitem(
                path=blog.path, name=blog.name, content_type='blog', item_id=blog.id)
            session.add(fileitem)
        session.commit()
        return {'status': True, 'msg': '%s/%s' % (blog.path, blog.name)}
    except BaseException as e:
        return {'status': False, 'msg': e}


def import_file():
    session = db.create_session()
    hlsitems = [item for item in session.query(db.Hlsitem)]
    for item in hlsitems:
        if len([item for item in session.query(db.Fileitem).filter_by(path=item.path, name=item.name)]):
            continue
        if item.content_type == 'd':
            fileitem = db.Fileitem(
                name=item.name, path=item.path, poster=item.poster, content_type='d')
        else:
            fileitem = db.Fileitem(name=item.name, path=item.path,
                                   poster=item.poster, content_type='hls', item_id=item.id)
        session.add(fileitem)
    logging.info('-' * 65)
    blogitems = [item for item in session.query(db.Blog)]
    for item in blogitems:
        if item.path is None:
            continue
        if len([item for item in session.query(db.Fileitem).filter_by(path=item.path.replace('/blog', '/root'), name=item.name)]):
            continue
        if item.content_type == 'd':
            fileitem = db.Fileitem(name=item.name, path=item.path.replace(
                '/blog', '/root'), content_type='d')
        else:
            fileitem = db.Fileitem(name=item.name, path=item.path.replace(
                '/blog', '/root'), content_type='blog', item_id=item.id)
        session.add(fileitem)
    logging.info('-' * 65)
    session.commit()


def get_file(fullpath):
    try:
        session = db.create_session()
        ppath, pname = fullpath.rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = None
        fileitem = session.query(db.Fileitem).filter_by(
            path=ppath, name=pname).first()
        if fileitem:
            if fileitem.content_type == 'd':
                return {'status': False, 'msg': '路径[%s]是文件' % fullpath}
            else:
                return {'status': True, 'msg': fileitem}
        else:
            return {'status': False, 'msg': '路径[%s]指向的文件不存在' % fullpath}
    except BaseException as e:
        return {'status': False, 'msg': e}


def rename(fullpath, name):
    try:
        session = db.create_session()
        ppath, pname = fullpath.rsplit('/', 1)
        if len(ppath) <= 0:
            return {'status': False, 'msg': '根目录[%s]不能修改' % fullpath}
        fileitem = session.query(db.Fileitem).filter_by(
            path=ppath, name=pname).first()
        if fileitem:
            if fileitem.content_type == 'd':
                return {'status': False, 'msg': '路径[%s]是文件' % fullpath}
            else:
                return {'status': True, 'msg': fileitem}
        else:
            return {'status': False, 'msg': '路径[%s]指向的文件不存在' % fullpath}
    except BaseException as e:
        return {'status': False, 'msg': e}


if __name__ == '__main__':
    help_msg = '''\
        Usage:python3 %s {option}
        -m: dirname         | mkdir dirname
        -r: oname nname | rename oname to nname
        -d: dirname          | delete dir
        -t: test
        --july: path    | update_july_data
        --july_src: filepath
        --flsav_src filepath
        --521av_src filepath
        --download_backend: path | download_backend
        --local: path   | load local m3u8
        --update_fls
        --import_file
        ---------------------------------------------------------
        [require]
        pip3 install SQLAlchemy==1.3.15 -i https://pypi.tuna.tsinghua.edu.cn/simple
        ''' % sys.argv[0]
    print(sys.argv)
    if len(sys.argv) < 2:
        print(help_msg)
    else:
        settings.get_config('dev')
        set_logger()
        if '-m' == sys.argv[1]:
            dirname = sys.argv[2]
            if os.path.exists(dirname):
                raise BaseException('file %s exists' % dirname)
            db.init_db('dev')
            parent, name = dirname.rsplit('/', 1)
            makedir(parent, name)
            exit(0)
        if '-r' == sys.argv[1]:
            oname = sys.argv[2]
            nname = sys.argv[3]
            db.init_db('dev')
            rename(oname, nname)
            exit(0)
        if '-d' == sys.argv[1]:
            dirname = sys.argv[2]
            db.init_db('dev')
            delete_by_path(dirname)
            exit(0)
        if '--july' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            update_july_data(sys.argv[2])
            exit(0)
        if '--july_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_july_data(sys.argv[2])
            exit(0)
        if '--flsav_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_fuliseav_data(sys.argv[2])
            exit(0)
        if '--521av_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_521_data(sys.argv[2])
            exit(0)
        if '--local' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            load_local(sys.argv[2])
            exit(0)
        if '-t' == sys.argv[1]:
            # url = 'https://s19.xyz/video/view/eympOn3rAoMNa7Vq'
            # dom_path = [{'video': {'attr': {'id': 'video-play'}, 'string': ''}}]
            # get_res = {'attrs': ['data-src', 'data-poster']}
            # result = load_src(url, dom_path, get_res)
            # print(result)
            db.init_db('dev')
            session = db.create_session()
            dir_ = '/root'
            print([item for item in session.query(db.Fileitem).filter(
                db.Fileitem.path.like('%s%%' % dir_), db.Fileitem.status == 0)])
            exit(0)
        # --update_fls
        if '--update_fls' == sys.argv[1]:
            db.init_db('dev')
            update_fuliseav_data()
            exit(0)
        # --import_file
        if '--import_file' == sys.argv[1]:
            db.init_db('dev')
            import_file()
            exit(0)
        print(help_msg)
